package com.archive.forum.service;

import com.archive.forum.dto.PaginationDTO;
import com.archive.forum.dto.PostDTO;
import com.archive.forum.exception.CustomizeException;
import com.archive.forum.exception.ExceptionEnum;
import com.archive.forum.mapper.PostExtMapper;
import com.archive.forum.mapper.PostMapper;
import com.archive.forum.mapper.UserLikeMapper;
import com.archive.forum.mapper.UserMapper;
import com.archive.forum.model.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class PostService {
    @Autowired
    private PostMapper postMapper;
    @Autowired
    private PostExtMapper postExtMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserLikeMapper userLikeMapper;

    //通用分页查询方法
    private PaginationDTO paginate(Integer page, Integer size,
                                   Function<Integer, Integer> countFunc,
                                   Function<RowBounds, List<PostWithBLOBs>> queryFunc) {
        PaginationDTO paginationDTO = new PaginationDTO();

        // 计算总数和总页数
        int totalCount = countFunc.apply(0);
        int totalPage = (totalCount + size - 1) / size;

        // 处理页码
        if (totalPage > 0) {
            page = Math.max(1, Math.min(page, totalPage));
        } else {
            page = 1;
            totalPage = 1;
        }

        // 执行查询
        int offset = size * (page - 1);
        List<PostWithBLOBs> posts = queryFunc.apply(new RowBounds(offset, size));

        // 转换为DTO
        List<PostDTO> postDTOS = posts.stream().map(post -> {
            PostDTO postDTO = new PostDTO();
            BeanUtils.copyProperties(post, postDTO);
            postDTO.setUser(userMapper.selectByPrimaryKey(post.getCreator()));
            return postDTO;
        }).collect(Collectors.toList());

        paginationDTO.setData(postDTOS);
        paginationDTO.setPagination(page, totalPage);
        return paginationDTO;
    }

    // 重构后的搜索方法
    public PaginationDTO search(String keyword, Integer page, Integer size) {
        return paginate(
                page, size,
                unused -> postExtMapper.countByKeyword(keyword),
                rb -> postExtMapper.searchByKeyword(keyword, rb.getOffset(), rb.getLimit())
        );
    }

    // 重构后的标签搜索方法
    public PaginationDTO searchtag(String tag, Integer page, Integer size) {
        return paginate(
                page, size,
                unused -> postExtMapper.countByTag(tag),
                rb -> postExtMapper.searchByTag(tag, rb.getOffset(), rb.getLimit())
        );
    }

    // 重构后的热门帖子方法
    public PaginationDTO listPopular(Integer page, Integer size, String period) {
        return paginate(
                page, size,
                unused -> {
                    PostExample example = buildTimeRangeExample(period);
                    return (int) postMapper.countByExample(example);
                },
                rb -> {
                    PostExample example = buildTimeRangeExample(period);
                    example.setOrderByClause("(like_count * 1.0 + comment_count * 1.2 + view_count * 0.1) DESC");
                    return postMapper.selectByExampleWithBLOBsWithRowbounds(example, rb);
                }
        );
    }
    // 重构后的从旧到新帖子方法
    public PaginationDTO listOldest(Integer page, Integer size) {
        return paginate(
                page, size,
                unused -> (int) postMapper.countByExample(new PostExample()),
                rb -> {
                    PostExample example = new PostExample();
                    example.setOrderByClause("gmt_modified ASC");
                    return postMapper.selectByExampleWithBLOBsWithRowbounds(example, rb);
                }
        );
    }
    // 重构后的默认帖子查询方法
    public PaginationDTO list(Integer page, Integer size) {
        return paginate(
                page, size,
                unused -> (int) postMapper.countByExample(new PostExample()),
                rb -> { 
                    PostExample example = new PostExample();
                    example.setOrderByClause("gmt_modified DESC");
                    return postMapper.selectByExampleWithBLOBsWithRowbounds(example, rb);
                }
        );
    }
    // 重构后的用户帖子查询方法
    public PaginationDTO listByUser(Integer userId, Integer page, Integer size) {
        return paginate(
                page, size,
                unused -> {
                    PostExample example = new PostExample();
                    example.createCriteria().andCreatorEqualTo(userId);
                    return (int) postMapper.countByExample(example);
                },
                rb -> {
                    PostExample example = new PostExample();
                    example.createCriteria().andCreatorEqualTo(userId);
                    example.setOrderByClause("gmt_create DESC"); // 按发布时间倒序
                    return postMapper.selectByExampleWithBLOBsWithRowbounds(example, rb);
                }
        );
    }
    // 构建时间范围查询条件
    private PostExample buildTimeRangeExample(String period) {
        PostExample example = new PostExample();
        long now = System.currentTimeMillis();

        switch (period) {
            case "weekly":
                example.createCriteria().andGmtModifiedBetween(now - (7 * 24 * 60 * 60 * 1000), now);
                break;
            case "monthly":
                example.createCriteria().andGmtModifiedBetween(now - (30L * 24 * 60 * 60 * 1000), now);
                break;
        }
        return example;
    }
    //查询帖子详情
    public PostDTO getById(Integer id, Integer currentUser) {
        Post post = postMapper.selectByPrimaryKey(id);
        PostDTO postDTO = new PostDTO();
        BeanUtils.copyProperties(post, postDTO);
        // 设置用户信息
        postDTO.setUser(userMapper.selectByPrimaryKey(post.getCreator()));
        // 检查当前用户是否点赞

        if (currentUser != null) {
            UserLikeExample example = new UserLikeExample();
            example.createCriteria()
                    .andUserIdEqualTo(currentUser)
                    .andTargetIdEqualTo(id)
                    .andTypeEqualTo(1); // 1表示帖子
            postDTO.setIsLiked(userLikeMapper.countByExample(example) > 0);
        }

        return postDTO;
    }
    public PostDTO getById(Integer id){
        Post post = postMapper.selectByPrimaryKey(id);
        if (post == null){
            throw new CustomizeException(ExceptionEnum.POST_NOT_FOUND);
        }
        PostDTO postDTO = new PostDTO();
        BeanUtils.copyProperties(post, postDTO);
        User user = userMapper.selectByPrimaryKey(post.getCreator());
        postDTO.setUser(user);
        return postDTO;
    }
    //创建或更新帖子
    public Integer createOrUpdate(PostWithBLOBs post) {
        if (post.getId() == null) {
            post.setGmtCreate(System.currentTimeMillis());
            post.setGmtModified(post.getGmtCreate());
            postExtMapper.insertSelective(post);
            return post.getId();
        }else {
            post.setGmtModified(System.currentTimeMillis());
           int update =  postMapper.updateByPrimaryKeySelective(post);
           if (update != 1) {
               throw new CustomizeException(ExceptionEnum.POST_NOT_FOUND);
           }
        }
        return post.getId(); // 返回原有ID
    }
    //删除帖子
    public void deletePost(String id) {
        postMapper.deleteByPrimaryKey(Integer.parseInt(id));
    }
    //高频调用，添加缓存
    @Cacheable(value = "hotTags", unless = "#result.empty")
    public List<String> getHotTags() {
        // 1. 查询最近7天的帖子
        Long sevenDaysAgo = System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000;
        PostExample example = new PostExample();
        example.createCriteria().andGmtModifiedGreaterThanOrEqualTo(sevenDaysAgo);
        List<Post> recentPosts = postMapper.selectByExample(example);

        // 2. 统计标签出现频率
        Map<String, Integer> tagFrequency = new HashMap<>();
        for (Post post : recentPosts) {
            if (post.getTag() != null && !post.getTag().isEmpty()) {
                String[] tags = post.getTag().split(",");
                for (String tag : tags) {
                    tagFrequency.put(tag, tagFrequency.getOrDefault(tag, 0) + 1);
                }
            }
        }

        // 3. 获取出现频率最高的3个标签
        return tagFrequency.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                .limit(3)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
    //阅读数累加
    public void incView(Integer id) {
        Post post =new Post();
        post.setId(id);
        post.setViewCount(1);
        postExtMapper.incView(post);
    }
    //展示相关帖子
    public List<PostDTO> selectRelated(PostDTO queryDTO) {
        if (StringUtils.isBlank(queryDTO.getTag())) {
            return new ArrayList<>();
        }
        String[] tags = StringUtils.split(queryDTO.getTag(), ",");
        String regexTag = String.join("|", tags);
        Post post = new Post();
        post.setId(queryDTO.getId());
        post.setTag(regexTag);
        //模糊查找tag
        List<Post> posts = postExtMapper.selectByTag(post);
        List<PostDTO> postDTOS = posts.stream().map(p -> {
            PostDTO postDTO = new PostDTO();
            BeanUtils.copyProperties(p, postDTO);
            return postDTO;
        }).collect(Collectors.toList());
        return postDTOS;
    }

    public Post findById(String id) {
        return postMapper.selectByPrimaryKey(Integer.parseInt(id));
    }


}
